package com.xiaoshuidi.cloud.module.contract.controller.admin.bill;


import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.excel.core.util.ExcelUtils;
import com.xiaoshuidi.cloud.framework.operatelog.core.annotations.OperateLog;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.OrderResp;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.ownerOrder.OwnerOrderTransferExcelVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.bill.vo.rentOrder.*;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.EnergyConsumptionImportExcelVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.contract.vo.HomeQueryVO;
import com.xiaoshuidi.cloud.module.contract.controller.admin.roommate.vo.ContractRoommateImportRespVO;
import com.xiaoshuidi.cloud.module.contract.convert.bill.MyRentOrderConvert;
import com.xiaoshuidi.cloud.module.contract.convert.bill.RentOrderConvert;
import com.xiaoshuidi.cloud.module.contract.convert.contract.ContractHouseOwnerConvert;
import com.xiaoshuidi.cloud.module.contract.dal.dataobject.bill.RentOrderDO;
import com.xiaoshuidi.cloud.module.contract.enums.ApiConstants;

import com.xiaoshuidi.cloud.module.contract.enums.ErrorCodeConstants;

import com.xiaoshuidi.cloud.module.contract.enums.bill.OrderTypeEnum;
import com.xiaoshuidi.cloud.module.contract.listener.RoommateUploadListener;
import com.xiaoshuidi.cloud.module.contract.service.bill.RentOrderService;
import com.xiaoshuidi.cloud.module.contract.util.bill.RemainingAmount;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import java.util.Objects;

import static com.xiaoshuidi.cloud.framework.common.pojo.CommonResult.error;

import static com.xiaoshuidi.cloud.framework.common.pojo.CommonResult.success;
import static com.xiaoshuidi.cloud.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;

@Tag(name = "管理后台 - 账单")
@RestController
@RequestMapping(ApiConstants.NAME + "/order")
@Validated
@Slf4j
public class RentOrderController {
    @Resource
    private RentOrderService rentOrderService;


    @PostMapping("/generate")
    @Operation(summary = "生成账单")
    public CommonResult<OrderResp> generateBills(@Valid @RequestBody RentOrderVO rentOrderVO) {
        if (rentOrderVO.getMonthRent() == null || rentOrderVO.getMonthRent().compareTo(BigDecimal.ZERO) <= 0) {
            return success(new OrderResp());
        }
        //账单集合
        OrderResp orderResp = null;
        if (Objects.isNull(rentOrderVO.getBillRules()) || rentOrderVO.getBillRules() == 0){
            // 按非自然月生成账单
            // 根据账单计算账单金额
            orderResp = DateRangeGenerator.calculateBillAmount(rentOrderVO);
        }else if (rentOrderVO.getBillRules() == 1){
            // 自然月生成账单
            orderResp = DateRangeGenerator.calculateNaturalMonthBillAmount(rentOrderVO);
        }
        if (Objects.isNull(orderResp)){
            return error(ErrorCodeConstants.CONTRACT_DATA_ABNORMAL);
        }
        BigDecimal totalRent = orderResp.getTotalRent();
        BigDecimal totalFeesAmount = orderResp.getTotalFeesAmount();
        BigDecimal totalDiscountValue = orderResp.getTotalDiscountValue();
        BigDecimal totalExtraDiscountValue = orderResp.getTotalExtraDiscountValue();
        orderResp.setTotalAmount(totalRent.add(totalFeesAmount).add(orderResp.getTotalDepositAmount()).subtract(totalDiscountValue).subtract(totalExtraDiscountValue));
        return success(orderResp);
    }

    @GetMapping("/remaining")
    @Operation(summary = "获取应退账单-根据合同id")
    @Parameter(name = "contractId", description = "合同id", required = true, example = "1024")
    public CommonResult<List<RemainingAmount>> getByContractId(@RequestParam("id") Long id) {
          List<RemainingAmount> remainingAmountList = rentOrderService.getByContractId(id);
        return success(remainingAmountList);
    }

    @PostMapping("/create")
    @Operation(summary = "创建杂费账单")
    public CommonResult createRentOrder(@Valid @RequestBody RentOrderCreateReq req) {
        req.setOrderType(OrderTypeEnum.CUSTOM.getCode());
        rentOrderService.createRentOrder(req);
        return success();
    }

    @PutMapping("/update")
    @Operation(summary = "更新账单")
    public CommonResult<Boolean> updateContractRentorder(@Valid @RequestBody RentOrderUpdateReqVO updateReqVO) {
        rentOrderService.updateContractRentOrder(updateReqVO);
        return success(true);
    }

    @DeleteMapping("/delete")
    @Operation(summary = "删除账单")
    @Parameter(name = "id", description = "编号", required = true)
    public CommonResult<Boolean> deleteContractRentOrder(@RequestParam("id") Long id) {
        rentOrderService.deleteContractRentOrder(id);
        return success(true);
    }

    @GetMapping("/get")
    @Operation(summary = "获得账单")
    @Parameter(name = "id", description = "编号", required = true, example = "1024")
    public CommonResult<RentOrderRespVO> getContractRentOrder(@RequestParam("id") Long id) {
        RentOrderDO rentorder = rentOrderService.getContractRentOrder(id);
        return success(RentOrderConvert.INSTANCE.convert(rentorder));
    }

    @GetMapping("/list")
    @Operation(summary = "获得账单列表")
    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
    public CommonResult<List<RentOrderRespVO>> getContractRentorderList(@RequestParam("ids") Collection<Long> ids) {
        List<RentOrderDO> list = rentOrderService.getContractRentOrderList(ids);
        return success(RentOrderConvert.INSTANCE.convertList(list));
    }

    @GetMapping("/get-order")
    @Operation(summary = "租客账单待处理、未出账、已处理")
    @Parameter(name = "contractId", description = "合同id", required = true, example = "1024")
    public CommonResult<RentOrderInfoVO> getBill(@RequestParam("id") Long id) {
        RentOrderInfoVO bill = rentOrderService.getRentOrder(id, Arrays.asList(OrderTypeEnum.DEFAULT.getCode(), OrderTypeEnum.CUSTOM.getCode(),
                OrderTypeEnum.EXTENSION.getCode(),OrderTypeEnum.METER.getCode()));
        return success(bill);
    }

    /**
     * 查看账单明细
     * @param id 账单id
     * @return
     */
    @GetMapping("/get-order-detail")
    @Operation(summary = "查看账单明细")
    @Parameter(name = "id", description = "账单id", required = true, example = "1024")
    public CommonResult<RentOrderDetailVO> getOrderDetail(@RequestParam("id") Long id) {
        RentOrderDetailVO bill = rentOrderService.getOrderDetail(id);
        return success(bill);
    }
//    @GetMapping("/export-excel")
//    @Operation(summary = "导出账单 Excel")
//    @PreAuthorize("@ss.hasPermission('contract:rent-order:export')")
//    @OperateLog(type = EXPORT)
//    public void exportRentOrderExcel(@Valid RentOrderExportReqVO exportReqVO, HttpServletResponse response) throws IOException {
//        List<RentOrderDO> list = rentOrderService.getRentOrderList(exportReqVO);
//        // 导出 Excel
//        List<RentOrderExcelVO> datas = RentOrderConvert.INSTANCE.convertList02(list);
//        ExcelUtils.write(response, "账单.xls", "数据", RentOrderExcelVO.class, datas);
//    }

    @GetMapping("/receivable-order")
    @Operation(summary = "获得某日期下的应收账单")
    public CommonResult<RentOrderHomeRespVO> getReceivableOrders(HomeQueryVO req) {
        RentOrderHomeRespVO receivableBills = rentOrderService.getReceivableOrders(req);
        return success(receivableBills);
    }

    /**
     * 查询账单
     */
    @PostMapping("/page")
    @Operation(summary = "获取租客账单列表分页")
    public CommonResult<Page<RentOrderResp>> getRentOrder(@Valid @RequestBody RentOrderQueryVo rentOrderQueryVo) {
        Page<RentOrderResp> result = rentOrderService.getRentOrder(rentOrderQueryVo);
        return success(result);
    }

    /**
     * 导出租客账单
     * */
    @GetMapping("/export-order")
    @Operation(summary = "导出租客账单 Excel")
//    @PreAuthorize("@ss.hasPermission('contract:export')")
    @OperateLog(type = EXPORT)
    public void exportOrderExcel(@ModelAttribute RentOrderQueryVo req, HttpServletResponse response) throws IOException {
//        List<RentOrderExcelVO> res = rentOrderService.exportOrder(req);
//        // 导出 Excel
//        ExcelUtils.write(response, "租客账单.xls", "数据", RentOrderExcelVO.class, res);
        exportOrderExcelPageList(req, response);

    }


    /**
     * 导出租客账单新
     */
    @GetMapping("/export-neworder")
    @Operation(summary = "导出租客账单 Excel")
    @OperateLog(type = EXPORT)
    public void exportOrderExcelPageList(@ModelAttribute RentOrderQueryVo req, HttpServletResponse response) throws IOException {
        req.setPageSize(100);
        // 导出 Excel
        PageResult<RentOrderResp> pageResult = rentOrderService.getRentOrderPage(req);
        ExcelUtils.write(response, "租客账单.xlsx", "数据", RentOrderExcelVO.class, pageResult,
                MyRentOrderConvert::convertList, pageNo -> {
                    req.setPageNo(pageNo);
                    return rentOrderService.getRentOrderPage(req);
                }
        );
    }

    /**
     * 查询合同账单
     */
    @GetMapping("/get-contract-order")
    @Operation(summary = "获取合同账单")
    @Parameter(name = "contractId", description = "合同id", required = true, example = "1024")
    public CommonResult<List<RentOrderRespVO>> getOrderByContractId(@RequestParam("id") Long id) {
        List<RentOrderRespVO> result = rentOrderService.getOrderByContractId(id);
        return success(result);
    }

    /**
     * 批量催款
     */
    @PostMapping("/order-collection")
    @Operation(summary = "获取合同账单")
    @Parameter(name = "contractId", description = "合同id", required = true, example = "1024")
    public CommonResult<String> orderCollection(@RequestBody List<Long> ids) {
        String msg = rentOrderService.orderCollection(ids);
        return success(msg);
    }

    /**
     * 判断首期账单是否支付
     */
    @GetMapping("/first-order")
    @Operation(summary = "判断首期账单是否支付")
    @Parameter(name = "contractId", description = "合同id", required = true, example = "1024")
    public CommonResult<Boolean> getFirstOrderPayStatus(@RequestParam("contractId") Long contractId) {
        Boolean aBoolean = rentOrderService.getFirstOrderPayStatus(contractId);
        return success(aBoolean);
    }

    /**
     * 企业账单待处理、未出账、已处理
     */
    @GetMapping("/get-company-order")
    @Operation(summary = "企业账单待处理、未出账、已处理")
    @Parameter(name = "companyContractId", description = "企业合同id", required = true, example = "1024")
    public CommonResult<RentOrderInfoVO> getCompanyOrders(@RequestParam("companyContractId") Long companyContractId) {
        return success(rentOrderService.getCompanyOrders(companyContractId));
    }

    @PostMapping("/get-company-batch")
    @Operation(summary = "获取企业账单批次号")
    @Parameter(name = "ids", description = "企业子账单ids", required = true, example = "1024")
    public CommonResult<String> getCompanyBatchNo(@RequestBody List<Long> ids) {
        String msg = rentOrderService.getCompanyBatchNo(ids);
        return success(msg);
    }

    /**
     * 企业催收
     */
    @PostMapping("/urge-company")
    @Operation(summary = "企业催收")
    public CommonResult<String> urgeCompanyPayOrder(@Valid @RequestBody CompanyOrderUrgeReqVO reqVO) {
        String msg = rentOrderService.urgeCompanyPayOrder(reqVO);
        return success(msg);
    }

    /**
     * 管家端app账单预览
     */
    @GetMapping("/get-order-contract")
    @Operation(summary = "管家端app账单预览")
    public CommonResult<List<RentOrderContractVO>> getContractOrder(@RequestParam("id") Long id) {
        List<RentOrderContractVO> msg = rentOrderService.getContractOrder(id);
        return success(msg);
    }

    /**
     * 导入 能耗账单
     * @param file
     * @return
     * @throws Exception
     */
    @PostMapping("/energyConsumptionImport")
    @Operation(summary = "导入能耗账单")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
    })
    public CommonResult<ContractRoommateImportRespVO> energyConsumptionImport(@RequestParam("file") MultipartFile file) throws Exception {
        List<EnergyConsumptionImportExcelVO> list =
                EasyExcel.read(file.getInputStream(), EnergyConsumptionImportExcelVO.class,
                        new RoommateUploadListener<EnergyConsumptionImportExcelVO>())
                        .autoCloseStream(false)
                        .sheet(0).doReadSync();
        return success(rentOrderService.energyConsumptionImport(list));
    }

    @GetMapping("/templateDownload")
    @Operation(summary = "导出能耗账单")
    @Parameters({
            @Parameter(name = "file", description = "Excel 文件", required = true),
    })
    public CommonResult<JSONObject> templateDownload(@RequestParam(required = false) Long apartmentId) {
        return success(rentOrderService.templateDownload(apartmentId));
    }

}
